#include "socket_handle.h"
#include <hal_tlv.h>
#include "hal_driver.h"
#include "hal_temp.h"
#include "hal_current.h"
#include "hal_eeprom.h"
#include "hal_configer.h"
#include "cfg_drive.h"
#include <common.h>
#include <tlv_cmd.h>
#include "sys_log.h"
#include "hal_errorcode.h"
#include "hal_EEpromWR.h"
#include "hal_socket.h"
#include "tlv_cmd.h"
#include "hal_tlv.h"

extern int (*laser_func_callback_fun[FUNC_LASER_TYPE_COUNT_E])(struct TLVPacket *);
extern TempCurrentParaSt g_TempCurrentRealValue;
extern uint32_t TA_CHANNEL_LD_ON_PIN_STATE;

int laser_func_00_fun(struct TLVPacket *packet) { return 1; }

// 电流源开关
int laser_func_01_fun(struct TLVPacket *packet)
{
    struct LaserSwitchMessageCmdSt *LaserSwitchMessageCmd = (struct LaserSwitchMessageCmdSt *)&(packet->value);

    ENDIANSWAP_DATA((LaserSwitchMessageCmd)->LaserChannelType);
    ENDIANSWAP_DATA((LaserSwitchMessageCmd)->LaserSwitchState);

    uint32_t lasernum    = LaserSwitchMessageCmd->LaserChannelType;
    uint32_t switchstate = LaserSwitchMessageCmd->LaserSwitchState;

    if (switchstate == LASER_SWITCH_STATE_ON_E)
    {
        HAL_CurrentDrivePinEnable(lasernum);

#if MODEL_CHOICE == MODEL_LASER_TA
        if (lasernum == LASER_NUMBER_CHAN_2)
        {
            TA_CHANNEL_LD_ON_PIN_STATE = GPIO_PIN_SET;
        }
#endif
    }
    else if (switchstate == LASER_SWITCH_STATE_OFF_E)
    {
        HAL_CurrentDrivePinDisEnable(lasernum);

#if MODEL_CHOICE == MODEL_LASER_TA
        if (lasernum == LASER_NUMBER_CHAN_2)
        {
            TA_CHANNEL_LD_ON_PIN_STATE = GPIO_PIN_RESET;
        }
#endif
    }

    ENDIANSWAP_DATA((LaserSwitchMessageCmd)->LaserChannelType);
    ENDIANSWAP_DATA((LaserSwitchMessageCmd)->LaserSwitchState);

    SLOG_I("laser current switch funcmd:%#x, lasernum:%d, switchstate:%s \t\r\n", packet->tagcmd, lasernum, (switchstate == LASER_SWITCH_STATE_ON_E) ? "OPEN" : "CLOSE");
    hal_SendPacketToUSART(packet);

    return 1;
}

// 一键读取当前实时值
int laser_func_02_fun(struct TLVPacket *packet)
{
    struct LaserMessageCmdSt *LaserMessageCmd = (struct LaserMessageCmdSt *)&(packet->value);

    ENDIANSWAP_DATA((LaserMessageCmd)->LaserChannelType);
    uint32_t lasernum = LaserMessageCmd->LaserChannelType;

    if (lasernum == LASER_NUMBER_CHAN_1)
    {
        LaserMessageCmd->LaserSubMessage.Current    = g_TempCurrentRealValue.Current_Chn_1;
        LaserMessageCmd->LaserSubMessage.Temp       = g_TempCurrentRealValue.Temperature_Chn_1;
        LaserMessageCmd->LaserSubMessage.TempCrtCur = g_TempCurrentRealValue.TempCtrCurrent_Chn_1;
    }
    else if (lasernum == LASER_NUMBER_CHAN_2)
    {
        LaserMessageCmd->LaserSubMessage.Current    = g_TempCurrentRealValue.Current_Chn_2;
        LaserMessageCmd->LaserSubMessage.Temp       = g_TempCurrentRealValue.Temperature_Chn_2;
        LaserMessageCmd->LaserSubMessage.TempCrtCur = g_TempCurrentRealValue.TempCtrCurrent_Chn_2;
        LaserMessageCmd->LaserSubMessage.PDCurent   = g_TempCurrentRealValue.Current_PD;
    }

    ENDIANSWAP_DATA((LaserMessageCmd)->LaserChannelType);

    SLOG_I("laser read all real data funcmd:%#x, lasernum:%d, Current:%.4f, Temp:%.4f, TempCrtCur:%.4f, PDCurent:%.4f  \t\r\n", 
    packet->tagcmd, lasernum, LaserMessageCmd->LaserSubMessage.Current, LaserMessageCmd->LaserSubMessage.Temp, LaserMessageCmd->LaserSubMessage.TempCrtCur,
    LaserMessageCmd->LaserSubMessage.PDCurent);
    
    hal_SendPacketToUSART(packet);

    return 1;
}

// 一键读取EEPROM值
int laser_func_03_fun(struct TLVPacket *packet)
{
    float tmp_cur, tmp_temp, tmp_pd = 0;

    EEPromParaSt EEPromPara;
    memset(&EEPromPara, 0, sizeof(EEPromPara));

    struct LaserMessageCmdSt *LaserMessageCmd = (struct LaserMessageCmdSt *)&(packet->value);

    ENDIANSWAP_DATA((LaserMessageCmd)->LaserChannelType);
    uint32_t lasernum = LaserMessageCmd->LaserChannelType;

    if (HAL_I2cEEPromRead(EEPROM_TEMP_CURRENT_SEED_ADDR, (uint8_t *)EEPromPara.EEp_CH1_Cur, sizeof(EEPromParaSt)) != HAL_OK)
    {
        hal_ErrorCodeWrite(ERRORCODE_TYPE_COM_SYSTEM, s_EEProm_Rd_Abnormal_Flag, 0, ABNORMAL_STATE);
        SLOG_I("laser_func_03_fun lasernum:%d, HAL_I2cEEPromRead error \t\r\n", lasernum);
    }

    if (lasernum == LASER_NUMBER_CHAN_1)
    {
        bytesToFloat(&tmp_cur, EEPromPara.EEp_CH1_Cur);
        bytesToFloat(&tmp_temp, EEPromPara.EEp_CH1_Temp);

        LaserMessageCmd->LaserSubMessage.Current = tmp_cur;
        LaserMessageCmd->LaserSubMessage.Temp    = tmp_temp;
    }
    else if (lasernum == LASER_NUMBER_CHAN_2)
    {
        bytesToFloat(&tmp_cur, EEPromPara.EEp_CH2_Cur);
        bytesToFloat(&tmp_temp, EEPromPara.EEp_CH2_Temp);
        bytesToFloat(&tmp_pd, EEPromPara.PD_Current);

        LaserMessageCmd->LaserSubMessage.Current  = tmp_cur;
        LaserMessageCmd->LaserSubMessage.Temp     = tmp_temp;
        LaserMessageCmd->LaserSubMessage.PDCurent = tmp_pd;
    }

    ENDIANSWAP_DATA((LaserMessageCmd)->LaserChannelType);

    SLOG_I("laser read all eeprom data funcmd:%#x, lasernum:%d, Current:%.4f, Temp:%.4f, PDCurent:%.4f \t\r\n", packet->tagcmd, lasernum, tmp_cur, tmp_temp, tmp_pd);

    hal_SendPacketToUSART(packet);

    return 1;
}

// 一键设置当前实时值
int laser_func_04_fun(struct TLVPacket *packet)
{
    struct LaserMessageCmdSt *LaserMessageCmd = (struct LaserMessageCmdSt *)&(packet->value);

    ENDIANSWAP_DATA((LaserMessageCmd)->LaserChannelType);
    uint32_t lasernum = LaserMessageCmd->LaserChannelType;

    float cur         = LaserMessageCmd->LaserSubMessage.Current;
    float temp        = LaserMessageCmd->LaserSubMessage.Temp;
    float power       = LaserMessageCmd->LaserSubMessage.PDCurent;
		//TA恒电流模式下的电流input值
		float taCur       = LaserMessageCmd->LaserSubMessage.Current;

    // 提前反馈，然后再执行后续步骤，因为后续步骤会延时
    SLOG_I("laser set all real data funcmd:%#x, lasernum:%d, Current:%.4f, Temp:%.4f, PDCurent:%.4f \t\r\n", packet->tagcmd, lasernum, cur, temp, power);

    hal_SendPacketToUSART(packet);

    if (lasernum == LASER_NUMBER_CHAN_1)
    {
		// 24.16ms
        Temp_Direct_Change(temp, lasernum);
		// 1.017s
        systick_delay_s(1);
        // 2.26s
        SeedCurrent_Slow_Change(cur, lasernum);
    }
    else if (lasernum == LASER_NUMBER_CHAN_2)
    {
        Temp_Direct_Change(temp, lasernum);
        systick_delay_s(1);
			//增加了对TA工作模式的判断，恒功率恒电流，这里修改函数参数
			//这里后续要更改的
#if MODEL_CHOICE == MODEL_LASER_TA
			if(TA_WORKING_MODE == TA_POWER_MODE){
				hal_TACurrentSlowChange(power, SAMPCUR_TYPE_PD_CURRENT);
			}
			else if(TA_WORKING_MODE == TA_CURRENT_MODE){
				hal_TACurrentSlowChange(power, SAMPCUR_TYPE_WORK_CURRENT);
			}
#elif MODEL_CHOICE == MODEL_LASER_DFB
        SeedCurrent_Slow_Change(cur, lasernum);
#endif
    }

    return 1;
}

// 一键设置EEPROM值
int laser_func_05_fun(struct TLVPacket *packet)
{
    struct LaserMessageCmdSt *LaserMessageCmd = (struct LaserMessageCmdSt *)&(packet->value);

    ENDIANSWAP_DATA((LaserMessageCmd)->LaserChannelType);
    uint32_t lasernum = LaserMessageCmd->LaserChannelType;

    float cur   = LaserMessageCmd->LaserSubMessage.Current;
    float temp  = LaserMessageCmd->LaserSubMessage.Temp;
    float power = LaserMessageCmd->LaserSubMessage.PDCurent;

    SLOG_I("laser set all epprom data funcmd:%#x, lasernum:%d, Current:%.4f, Temp:%.4f, PDCurent:%.4f \t\r\n", packet->tagcmd, lasernum, cur, temp, power);

    hal_SendPacketToUSART(packet);

    EEPromParaSt EEPromPara;
    memset(&EEPromPara, 0, sizeof(EEPromPara));

    if (HAL_I2cEEPromRead(EEPROM_TEMP_CURRENT_SEED_ADDR, (uint8_t *)EEPromPara.EEp_CH1_Cur, sizeof(EEPromParaSt)) != HAL_OK)
    {
        hal_ErrorCodeWrite(ERRORCODE_TYPE_COM_SYSTEM, s_EEProm_Rd_Abnormal_Flag, 0, ABNORMAL_STATE);
        SLOG_I("laser_func_05_fun lasernum:%d, HAL_I2cEEPromRead error \t\r\n", lasernum);
    }

    if (lasernum == LASER_NUMBER_CHAN_1)
    {
        Temp_Copy_To_EEPROM(lasernum, temp, EEPromPara.EEp_CH1_Temp);
        Current_Copy_To_EEPROM(lasernum, cur, EEPromPara.EEp_CH1_Cur);
    }
    else if (lasernum == LASER_NUMBER_CHAN_2)
    {
        Temp_Copy_To_EEPROM(lasernum, temp, EEPromPara.EEp_CH2_Temp);
        Current_Copy_To_EEPROM(lasernum, cur, EEPromPara.EEp_CH2_Cur);
        Power_Copy_To_EEPROM(lasernum, power, EEPromPara.PD_Current);
    }

    if (HAL_I2cEEPromWrite(EEPROM_TEMP_CURRENT_SEED_ADDR, (uint8_t *)EEPromPara.EEp_CH1_Cur, sizeof(EEPromParaSt)) != HAL_OK)
    {
        hal_ErrorCodeWrite(ERRORCODE_TYPE_COM_SYSTEM, s_EEProm_Wt_Abnormal_Flag, 0, ABNORMAL_STATE);
        SLOG_I("laser_func_05_fun lasernum:%d, HAL_I2cEEPromWrite error \t\r\n", lasernum);
    }

    return 1;
}

// 获取版本号
int laser_func_06_fun(struct TLVPacket *packet)
{
    struct LaserVersionCmdSt *LaserVersionCmd = (struct LaserVersionCmdSt *)&(packet->value);
    LaserVersionCmd->Version = DEVICE_VERSION;

    SLOG_I("laser read vension funcmd:%#x, vension:%#x \t\r\n", packet->tagcmd, (uint16_t)DEVICE_VERSION);

    hal_SendPacketToUSART(packet);

    return 1;
}

// 软件复位
int laser_func_07_fun(struct TLVPacket *packet)
{
#if MODEL_CHOICE == MODEL_LASER_TA
    hal_SeedCurrentSlowChange(0, CURRENT_SEPARAT_SEED,LASER_NUMBER_CHAN_1);
    systick_delay_ms(5);
    //hal_TACurrentSlowChange(0, SAMPCUR_TYPE_WORK_CURRENT);
		hal_SeedCurrentSlowChange(0, CURRENT_SEPARAT_SEED,LASER_NUMBER_CHAN_2);
		//hal_PDCurrentSlowChange(0, LASER_NUMBER_CHAN_2);
    systick_delay_ms(5);
#elif MODEL_CHOICE == MODEL_LASER_DFB
    hal_SeedCurrentSlowChange(0, CURRENT_SEPARAT_SEED, LASER_NUMBER_CHAN_1);
    systick_delay_ms(5);
    hal_SeedCurrentSlowChange(0, CURRENT_SEPARAT_SEED, LASER_NUMBER_CHAN_2);
    systick_delay_ms(5);
#endif

    LASER_GPIO_WRITE_PIN(CH1_REG_LD_EN, GPIO_PIN_SET);
    systick_delay_ms(5);
    LASER_GPIO_WRITE_PIN(CH2_REG_LD_EN, GPIO_PIN_SET);
    systick_delay_ms(5);

    LASER_GPIO_WRITE_PIN(CH1_REG_SHDN, GPIO_PIN_RESET);
    systick_delay_ms(5);
    LASER_GPIO_WRITE_PIN(CH2_REG_SHDN, GPIO_PIN_RESET);
    systick_delay_ms(5);

    SLOG_I("laser reset funcmd:%#x, TC data is 0, TC driver is close \t\r\n", packet->tagcmd);

    HAL_NVIC_SystemReset();

    return 1;
}

// 小型化中获取轮询数据和错误码
int laser_func_08_fun(struct TLVPacket *packet)
{
    struct LaserPollCmdSt *LaserPollCmd = (struct LaserPollCmdSt *)&(packet->value);

    LaserPollCmd->Channel_Current    = g_TempCurrentRealValue.Current_Chn_1;
    LaserPollCmd->Channel_Temp       = g_TempCurrentRealValue.Temperature_Chn_1;
    LaserPollCmd->Channel_TempCrtCur = g_TempCurrentRealValue.TempCtrCurrent_Chn_1;
    LaserPollCmd->Channe2_Current    = g_TempCurrentRealValue.Current_Chn_2;
    LaserPollCmd->Channe2_Temp       = g_TempCurrentRealValue.Temperature_Chn_2;
    LaserPollCmd->Channe2_TempCrtCur = g_TempCurrentRealValue.TempCtrCurrent_Chn_2;
    LaserPollCmd->Channe2_PDCurrent  = g_TempCurrentRealValue.Current_PD;

    for (int laserNum = 1; laserNum <= 2; laserNum++)
    {
        // 激光器的引脚相关错误码更新
        hal_LaserGpioPinStateRead(laserNum);

        hal_ErrorcodeRead(ERRORCODE_TYPE_LASER, laserNum, &LaserPollCmd->ErrorCode[laserNum - 1]);
    }

    SLOG_I("laser poll funcmd:%#x, errorcode:%#x, %#x, Current1:%.4f, Temp1:%.4f, TempCrtCur1:%.4f, Current2:%.4f, Temp2:%.4f, TempCrtCur2:%.4f, PDCurent2:%.4f \t\r\n", 
    packet->tagcmd, LaserPollCmd->ErrorCode[0], LaserPollCmd->ErrorCode[1], LaserPollCmd->Channel_Current, LaserPollCmd->Channel_Temp,
    LaserPollCmd->Channel_TempCrtCur, LaserPollCmd->Channe2_Current, LaserPollCmd->Channe2_Temp, LaserPollCmd->Channe2_TempCrtCur, LaserPollCmd->Channe2_PDCurrent);

    hal_SendPacketToUSART(packet);

    return 1;
}

int laser_func_09_fun(struct TLVPacket *packet)
{
    struct LaserRefreshCodeCmdSt *LaserRefreshCodeCmd = (struct LaserRefreshCodeCmdSt *)&(packet->value);

    hal_ErrorcodeReset();

    SLOG_I("laser errorcode refresh funcmd:%#x \t\r\n", packet->tagcmd);

    hal_SendPacketToUSART(packet);

    return 1;
}

int laser_func_0A_fun(struct TLVPacket *packet)
{
    struct LaserParameterCmdSt *LaserParameterCmd = (struct LaserParameterCmdSt *)&(packet->value);

    #if MODEL_CHOICE == MODEL_LASER_DFB
        strcpy(LaserParameterCmd->name, "laser_dfb");
        LaserParameterCmd->temp_init_wait_times = TEMP_INIT_WAIT_TIME_S;
        LaserParameterCmd->laser_dfb.temp_limit.low_limit = TEMP_LOW_LIMIT;
        LaserParameterCmd->laser_dfb.temp_limit.high_limit = TEMP_HIGH_LIMIT;    
        LaserParameterCmd->laser_dfb.seed_cur_limit.low_limit = CURRENT_LOW_LIMIT_DFB_LASER_SEED;
        LaserParameterCmd->laser_dfb.seed_cur_limit.high_limit = CURRENT_HIGH_LIMIT_DFB_LASER_SEED;

        SLOG_I("laser parameter funcmd:%#x, typename:%s, wait_time:%d, temp_limit:%.4f, %.4f, cur_limit:%.4f, %.4f \t\r\n", 
        packet->tagcmd, LaserParameterCmd->name, TEMP_INIT_WAIT_TIME_S, TEMP_LOW_LIMIT, TEMP_HIGH_LIMIT, CURRENT_LOW_LIMIT_DFB_LASER_SEED, CURRENT_HIGH_LIMIT_DFB_LASER_SEED);
    #elif MODEL_CHOICE == MODEL_LASER_TA
        strcpy(LaserParameterCmd->name, "laser_ta");
        LaserParameterCmd->temp_init_wait_times = TEMP_INIT_WAIT_TIME_S;
        LaserParameterCmd->laser_ta.temp_limit.low_limit = TEMP_LOW_LIMIT;
        LaserParameterCmd->laser_ta.temp_limit.high_limit = TEMP_HIGH_LIMIT;    
        LaserParameterCmd->laser_ta.seed_cur_limit.low_limit = CURRENT_LOW_LIMIT_DFB_LASER_SEED;
        LaserParameterCmd->laser_ta.seed_cur_limit.high_limit = CURRENT_HIGH_LIMIT_DFB_LASER_SEED;
        LaserParameterCmd->laser_ta.ta_pd_cur_limit.low_limit = CURRENT_LOW_LIMIT_TA_LASER_PD;
        LaserParameterCmd->laser_ta.ta_pd_cur_limit.high_limit = CURRENT_HIGH_LIMIT_TA_LASER_PD;
        LaserParameterCmd->laser_ta.ta_work_cur_limit.low_limit = CURRENT_LOW_LIMIT_TA_LASER_TA;
        LaserParameterCmd->laser_ta.ta_work_cur_limit.high_limit = CURRENT_HIGH_LIMIT_TA_LASER_TA;

        SLOG_I("laser parameter funcmd:%#x, typename:%s, wait_time:%d, temp_limit:%.4f, %.4f, seed_cur_limit:%.4f, %.4f, ta_cur_limit:%.4f, %.4f, pd_cur_limit:%.4f, %.4f \t\r\n", 
        packet->tagcmd, LaserParameterCmd->name, TEMP_INIT_WAIT_TIME_S, (float)TEMP_LOW_LIMIT, (float)TEMP_HIGH_LIMIT, (float)CURRENT_LOW_LIMIT_DFB_LASER_SEED, (float)CURRENT_HIGH_LIMIT_DFB_LASER_SEED,
        (float)CURRENT_LOW_LIMIT_TA_LASER_PD, (float)CURRENT_HIGH_LIMIT_TA_LASER_PD, (float)CURRENT_LOW_LIMIT_TA_LASER_TA, (float)CURRENT_HIGH_LIMIT_TA_LASER_TA);
    #endif

    hal_SendPacketToUSART(packet);

    return 1;
}

//函数指针数组，响应不同cmd命令
int (*laser_func_callback_fun[FUNC_LASER_TYPE_COUNT_E])(struct TLVPacket *) = {laser_func_00_fun, laser_func_01_fun, laser_func_02_fun, laser_func_03_fun, laser_func_04_fun,
                                                                               laser_func_05_fun, laser_func_06_fun, laser_func_07_fun, laser_func_08_fun, laser_func_09_fun,
                                                                               laser_func_0A_fun};
